home *** CD-ROM | disk | FTP | other *** search
- /*
- ** patch.library
- **
- ** Copyright © 1993-1997 by Stefan Fuchs
- ** Freely distributable.
- */
-
- #ifndef _PATCH_INCLUDES_H
- #include "patch_includes.h"
- #endif
-
- /****i* patch.library/FindPatchNotify ***************************************
- *
- * NAME
- * FindPatchNotify -- Find the notify structure with the given msgport.
- *
- * SYNOPSIS
- * node = FindPatchNotify( msgport )
- *
- * struct Node *FindPatchNotify( struct MsgPort *);
- *
- * FUNCTION
- * Find the notify structure belonging to the given messageport.
- *
- * INPUTS
- * msgport = pointer to a message port
- *
- * RESULT
- * node = Pointer to the node with the given messageport or NULL, if
- * not found.
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- struct Node *FindPatchNotify( struct MsgPort *msgport)
- {
- struct Node *Pointer;
-
- for (Pointer = (struct Node *) (PatchBase->PB_NotifyListHeader.lh_Head);
- Pointer->ln_Succ;
- Pointer = (struct Node *)Pointer->ln_Succ)
- {
- if((struct MsgPort *)Pointer->ln_Name == msgport) return(Pointer);
- }
- return(NULL);
- }
-
-
- /****i* patch.library/SendNotify ***************************************
- *
- * NAME
- * SendNotify -- Send messages to all notify messageports
- *
- * SYNOPSIS
- * SendNotify( code, patch )
- *
- * SendNotify( ULONG, struct Patch *);
- *
- * FUNCTION
- * Send PatchNotify messages to all notify messageports.
- * The memory for the messages and a replyport will be allocated.
- * This functions returns only, if all messages have been send back.
- *
- * INPUTS
- * code = PATCOD_xxx code indicating type of change (see patch.h)
- * patch = optional pointer to patch structure
- *
- * RESULT
- *
- * NOTES
- * If an error occurs (out of memory), no messages might be send.
- *
- * BUGS
- *
- * SEE ALSO
- * AddPatchNotifyA(), patch.h
- *
- ******************************************************************************
- *
- */
-
- void SendNotify( ULONG code, struct Patch *patch)
- {
- struct Node *pointer;
- struct PatchNotifyMessage *msg;
- struct MsgPort *port;
-
- if( msg = BAllocmem(sizeof(struct PatchNotifyMessage), MEMF_CLEAR| MEMF_PUBLIC))
- {
- if( port = CreateMsgPort())
- {
- msg->pnm_ExecMessage.mn_ReplyPort = port;
- msg->pnm_ExecMessage.mn_Length = sizeof(struct PatchNotifyMessage);
- msg->pnm_Class = PATCHNOTIFY_CLASS;
- msg->pnm_Code = code;
- msg->pnm_Object = patch;
-
- for (pointer = (struct Node *)PatchBase->PB_NotifyListHeader.lh_Head;
- pointer->ln_Succ;
- pointer = (struct Node *)pointer->ln_Succ)
-
- {
- PutMsg( (struct MsgPort *)(pointer->ln_Name), (struct Message *)msg);
- WaitPort( port);
- GetMsg( port);
- }
- DeleteMsgPort( port);
- }
- AFreemem( msg);
- }
- }
- /****i* patch.library/GetMasterPatch ***************************************
- *
- * NAME
- * GetMasterPatch -- Return the MasterPatch structure a Patch structure
- * belongs to
- *
- * SYNOPSIS
- * master = GetMasterPatch( patch )
- *
- * struct MasterPatch *GetMasterPatch( struct Patch *);
- *
- * FUNCTION
- * Return a pointer to the MasterPatch structure of a Patch structure.
- *
- * INPUTS
- * patch = pointer to a patch structure
- *
- * RESULT
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- struct MasterPatch *GetMasterPatch(struct Patch *patch)
- {
- return( (struct MasterPatch *)(((UBYTE *)GetListNodeHeader( (struct Node *)patch)) -offsetof(struct MasterPatch, MPS_PatchHeader)));
- }
-
-
- /****i* patch.library/DisconnectStartType ***************************************
- *
- * NAME
- * DisconnectStartType -- Return a library's jumptable to its original state
- *
- * SYNOPSIS
- * error = DisconnectStartType( master )
- *
- * ULONG error DisconnectStartType( struct MasterPatch *);
- *
- * FUNCTION
- * Return a library's jumptable to its original state and therefore
- * no patch.library patchcodes will be called for this function.
- * This function can fail, if a non-patch.library patch has been
- * installed after our own one.
- * This function will change the jump-table with Setfunction or
- * an own replacement routine, depending on wether the patch
- * was installed with SetFunction or not.
- *
- * INPUTS
- * master = pointer to a MasterPatch structure
- *
- * RESULT
- * error = errorcode as defined in patch.h
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- * patch.h, ConnectStartType()
- *
- ******************************************************************************
- *
- */
-
-
- #define INSTR_JMP 0x4ef9
-
- ULONG DisconnectStartType( struct MasterPatch *master)
- {
- ULONG Result = PATERR_Ok;
- struct Patch *starttype;
- UBYTE *memptr;
-
- if( master->MPS_Flags & MPSF_Attached)
- {
- starttype = (struct Patch *)FindType( (struct List *)&(master->MPS_PatchHeader), PS_TYPE_START);
- if( master->MPS_Flags & MPSF_UseSetFunction)
- {
- Disable();
- memptr = SetFunction( master->MPS_PatchedLibraryBase, master->MPS_PatchedLVO, master->MPS_SetFunctionResult);
- if( memptr != &(starttype->PS_PatchCode->PC_PatchCodeStart))
- {
- SetFunction( master->MPS_PatchedLibraryBase, master->MPS_PatchedLVO, (ULONG (*)())memptr);
- Result = PATERR_PatchInstalled;
- }
- Enable();
- }
- else
- {
- memptr = (UBYTE *)master->MPS_PatchedLibraryBase;
- memptr += master->MPS_PatchedLVO;
- Disable();
- if( *((UWORD *)memptr) == INSTR_JMP)
- {
- memptr += 2;
- if( ((ULONG *)memptr)[0] == (ULONG)(&(starttype->PS_PatchCode->PC_PatchCodeStart)))
- {
- *((ULONG *)memptr) = master->MPS_OldEntry02;
- memptr -= 2;
- *((UWORD *)memptr) = master->MPS_OldEntry01;
- CacheClearU();
- master->MPS_PatchedLibraryBase->lib_Flags |= LIBF_CHANGED;
- SumLibrary(master->MPS_PatchedLibraryBase);
- }
- else Result = PATERR_PatchInstalled;
- }
- else Result = PATERR_PatchInstalled;
- Enable();
- }
- if( Result == PATERR_Ok)
- master->MPS_Flags &= ~MPSF_Attached;
- }
- return(Result);
- }
-
-
- /****i* patch.library/ConnectStartType ***************************************
- *
- * NAME
- * ConnectStartType -- Change a library's jump-table, to point to
- * the StartType patchcode
- *
- * SYNOPSIS
- * error = ConnectStartType( master )
- *
- * ULONG error ConnectStartType( struct MasterPatch *);
- *
- * FUNCTION
- * Change a library's jump-table, to point to the StartType patchcode.
- *
- * This function can fail, if the jump-table entry is not in the standard
- * format.
- * This function will change the jump-table with Setfunction or
- * an own replacement routine, depending on wether PatchSetFunc is
- * active or not.
- *
- * INPUTS
- * master = pointer to a MasterPatch structure
- *
- * RESULT
- * error = errorcode as defined in patch.h
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- * patch.h, DisconnectStartType()
- *
- ******************************************************************************
- *
- */
-
-
- ULONG ConnectStartType( struct MasterPatch *master)
- {
- ULONG Result = PATERR_Ok;
- struct Patch *starttype;
- UBYTE *memptr;
-
- if( (master->MPS_Flags & MPSF_Attached) == NULL)
- {
- if( master->MPS_PatchedLibraryBase)
- {
- Result = FillOrigType(master);
- if( Result == PATERR_Ok)
- {
- if(starttype = (struct Patch *)FindType( (struct List *)&(master->MPS_PatchHeader), PS_TYPE_START))
- {
- master->MPS_Flags |= MPSF_Attached;
- if( master->MPS_Flags & MPSF_UseSetFunction)
- {
- master->MPS_SetFunctionResult = SetFunction( master->MPS_PatchedLibraryBase, master->MPS_PatchedLVO, (ULONG (*)())&(starttype->PS_PatchCode->PC_PatchCodeStart));
- }
- else
- {
- memptr = (UBYTE *)master->MPS_PatchedLibraryBase;
- memptr += master->MPS_PatchedLVO;
- Disable();
- *((UWORD *)memptr) = INSTR_JMP;
- memptr += 2;
- *((ULONG *)memptr) = (ULONG)&(starttype->PS_PatchCode->PC_PatchCodeStart);
- CacheClearU();
- master->MPS_PatchedLibraryBase->lib_Flags |= LIBF_CHANGED;
- SumLibrary(master->MPS_PatchedLibraryBase);
- Enable();
- }
- }
- }
- }
- }
- return( Result);
- }
-
-
- /****i* patch.library/FillOrigType ***************************************
- *
- * NAME
- * FillOrigType -- Set certain parameters for OrigType patch structures
- *
- * SYNOPSIS
- * error = FillOrigType( master )
- *
- * ULONG error FillOrigType( struct MasterPatch *);
- *
- * FUNCTION
- * Read the from the library's jump-table and check, if it is in a format
- * patch.library understands.
- * Check, if PatchSetFunc is running and set the appropriate flags.
- * This function can fail, if the jump-table entry is not in the standard
- * format.
- *
- * INPUTS
- * master = pointer to a MasterPatch structure
- *
- * RESULT
- * error = errorcode as defined in patch.h
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- * patch.h, ConnectStartType()
- *
- ******************************************************************************
- *
- */
- ULONG FillOrigType( struct MasterPatch *master)
- {
- struct TagItem taglist[2] =
- { {PATT_PatchName, (ULONG) ("PatchSetFunc")},
- TAG_DONE
- };
- struct Patch *origtype;
- UBYTE *memptr;
-
- memptr = (UBYTE *)master->MPS_PatchedLibraryBase;
- memptr += master->MPS_PatchedLVO;
-
- Disable();
- master->MPS_OldEntry01 = *((UWORD *)memptr);
- memptr += 2;
- master->MPS_OldEntry02 = *((ULONG *)memptr);
- Enable();
-
- origtype = (struct Patch *)FindType( (struct List *)&(master->MPS_PatchHeader), PS_TYPE_ORIG);
-
- if( master->MPS_OldEntry01 != INSTR_JMP)
- return(PATERR_FuncNotStd);
-
- memptr = origtype->PS_Jsr;
- memptr += 2;
- *((ULONG *)memptr) = master->MPS_OldEntry02;
-
- if( PatchBase->PB_Flags & PBF_PatchSetFuncActive)
- return(PATERR_Ok);
-
- if( FindPatchTagsA( taglist))
- return(PATERR_Ok);
-
- master->MPS_Flags |= MPSF_UseSetFunction;
- return(PATERR_Ok);
- }
-
- /****i* patch.library/TestUsage ***************************************
- *
- * NAME
- * TestUsage -- Test, if a patchcode is in use by any task
- *
- * SYNOPSIS
- * error = TestUsage( patch )
- *
- * ULONG error TestUsage( struct Patch *);
- *
- * FUNCTION
- * Test, if a patchcode is in use by any task.
- * If the global CheckPC flag is turned off, only test the usage counters,
- * otherwise also check all tasks and compare their program-counters
- * against specific memory locations not covered by the usage-counters.
- * Skip these tests for certain OS-functions.
- *
- * INPUTS
- * patch = pointer to a Patch structure or NULL for no action.
- *
- * RESULT
- * error = errorcode as defined in patch.h
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- #define LVORemTask -288
- #define LVOExit -144
-
-
- ULONG TestUsage( struct Patch *patch)
- {
- struct MasterPatch *master;
- struct Task *task;
-
- if( patch)
- {
- master = GetMasterPatch( patch);
-
- /* exec/Remtask(0) does not return from rts, so ignore invalid UsageCounter */
- if( (master->MPS_PatchedLVO == LVORemTask) && strcmp( "exec.library", master->MPS_Node.ln_Name) == NULL)
- return( PATERR_Ok);
-
- /* dos/Exit(0) does not return from rts, so ignore invalid UsageCounter */
- if( (master->MPS_PatchedLVO == LVOExit) && strcmp( "dos.library", master->MPS_Node.ln_Name) == NULL)
- return( PATERR_Ok);
- if( patch->PS_PatchCode->PC_Usage)
- {
- return(PATERR_PatchInUse);
- }
- if( PatchBase->PB_Flags & PBF_CheckPC == NULL)
- return(PATERR_Ok);
-
- Disable();
- for (task = (struct Task *) (SysBase->TaskReady.lh_Head);
- task->tc_Node.ln_Succ;
- task = (struct Task *)task->tc_Node.ln_Succ)
- {
- if(TestPCUsage( patch, GetPC( task->tc_SPReg, SysBase)))
- {
- Enable();
- return(PATERR_PatchInUse);
- }
- }
-
- for (task = (struct Task *) (SysBase->TaskWait.lh_Head);
- task->tc_Node.ln_Succ;
- task = (struct Task *)task->tc_Node.ln_Succ)
- {
- if(TestPCUsage( patch, GetPC( task->tc_SPReg, SysBase)))
- {
- Enable();
- return(PATERR_PatchInUse);
- }
- }
- Enable();
- }
- return(PATERR_Ok);
- }
-
-
- /****i* patch.library/TestPCUsage ***************************************
- *
- * NAME
- * TestPCUsage -- Compare certain memory adresses against a PC
- *
- * SYNOPSIS
- * error = TestPCUsage( patch, PC)
- *
- * ULONG error TestPCUsage( struct Patch *, APTR);
- *
- * FUNCTION
- * Compare certain memory adresses against a programm-counter.
- *
- * INPUTS
- * patch = pointer to a Patch structure.
- * PC = pointer to the next instruction, to be executed.
- *
- * RESULT
- * error = 0: Code is not in use
- * 1: Code is in use
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- ULONG TestPCUsage( struct Patch *patch, APTR pc)
- {
- if(patch->PS_TestUsage1 == pc)
- return 1;
- if(patch->PS_TestUsage2 == pc)
- return 1;
- if(patch->PS_TestUsage3 == pc)
- return 1;
- return 0;
- }
-
-
- /****i* patch.library/ReCalcStackSize ***************************************
- *
- * NAME
- * ReCalcStackSize -- Calculate the highest required stacksize
- *
- * SYNOPSIS
- * ReCalcStackSize( master)
- *
- * ReCalcStackSize( struct MasterPatch *);
- *
- * FUNCTION
- * Calculate the highest required stacksize for all patches and
- * place it, into the StartTypes stack fieled
- * If the stacksize has changed, allocate memory for stack caching.
- *
- * INPUTS
- * master = pointer to a MasterPatch structure.
- *
- * RESULT
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- void ReCalcStackSize( struct MasterPatch *master)
- {
- ULONG StackSize = 0;
- struct Patch *patch;
-
- for( patch = (struct Patch *)master->MPS_PatchHeader.mlh_Head;
- patch->PS_Node.ln_Succ;
- patch= (struct Patch *)patch->PS_Node.ln_Succ)
- {
- if(( patch->PS_Node.ln_Type == PS_TYPE_USER) || ( patch->PS_Node.ln_Type == PS_TYPE_SYSTEM) || ( patch->PS_Node.ln_Type == PS_TYPE_ORIG))
- {
- if( patch->PS_StackSize > StackSize)
- StackSize = patch->PS_StackSize;
- }
- }
-
- patch= (struct Patch *)FindType( (struct List *)(&(master->MPS_PatchHeader)), PS_TYPE_START);
- if(patch->PS_PatchCode->PC_StackSize != StackSize)
- {
- patch->PS_PatchCode->PC_StackSize = StackSize;
- PreAllocatedStacksAlloc( master, StackSize );
- }
- }
-
- /****i* patch.library/PreAllocatedStacksAlloc ***************************************
- *
- * NAME
- * PreAllocatedStacksAlloc -- Allocate memory for stack extension
- *
- * SYNOPSIS
- * PreAllocatedStacksAlloc( master, stacksize)
- *
- * PreAllocatedStacksAlloc( struct MasterPatch *, ULONG);
- *
- * FUNCTION
- * Allocate memory for stack extension of the given stacksize and
- * fill the slots in the masterpatch structure.
- * A stacksize, of null frees all slots.
- *
- * INPUTS
- * master = pointer to a MasterPatch structure.
- * stacksize = number of bytes to allocate
- *
- * RESULT
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- void PreAllocatedStacksAlloc( struct MasterPatch *master, ULONG stacksize)
- {
- ULONG stacks, i;
-
- PreAllocatedStacksFree( master);
-
- if(stacksize)
- {
- stacks = MIN(STACKSLOTS,PatchBase->PB_StackExtensions);
- if( stacks)
- {
- for( i = 0; i < stacks; i++)
- {
- master->MPS_StackSlots[i] = AllocStack(stacksize);
- }
- }
- }
- }
- /****i* patch.library/PreAllocateStacksFree ***************************************
- *
- * NAME
- * PreAllocatedStacksFree -- Free memory for stack extension
- *
- * SYNOPSIS
- * PreAllocatedStacksFree( master)
- *
- * PreAllocatedStacksFree( struct MasterPatch *);
- *
- * FUNCTION
- * Free memory for stack extension
- *
- *
- * INPUTS
- * master = pointer to a MasterPatch structure.
- *
- * RESULT
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- void PreAllocatedStacksFree( struct MasterPatch *master)
- {
- ULONG i;
- struct PatchStack *patchstack;
-
- for( i = 0; i < STACKSLOTS; i++)
- {
- patchstack = master->MPS_StackSlots[i];
- master->MPS_StackSlots[i] = 0;
- FreeStack( patchstack );
- }
- }
-
- /****i* patch.library/AllocStack ***************************************
- *
- * NAME
- * AllocStack -- Allocate and initialize a new stack
- *
- * SYNOPSIS
- * patchstack = AllocStack( stacksize )
- *
- * APTR AllocStack( ULONG);
- *
- * FUNCTION
- * Allocate memory for stack extension
- *
- *
- * INPUTS
- * stacksize = number of bytes, the new stack should hold.
- *
- * RESULT
- * patchstack = pointer to a PatchStack structure or NULL on failure.
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- struct PatchStack *AllocStack( ULONG stacksize )
- {
- APTR stack;
- struct PatchStack *patchstack = NULL;
-
- stack = AllocVec(stacksize + sizeof(struct PatchStack) + 8, MEMF_PUBLIC);
- if(stack )
- {
- patchstack = (struct PatchStack *)((UBYTE *)stack + stacksize);
- patchstack->PST_Reserved2 = 0xCCDDEEFF;
- patchstack->PST_Reserved1 = 0x8899AABB;
-
- patchstack->PST_StackSwap.stk_Upper = (ULONG) patchstack;
- patchstack->PST_StackSwap.stk_Lower = stack;
-
- patchstack->PST_Usage = 0L;
- patchstack->PST_Stacksize = stacksize;
- patchstack->PST_Magic2 = &patchstack->PST_Magic1;
- patchstack->PST_Magic1 = 0x50415443; /* 'PATC' */
- }
- return( patchstack);
- }
- /****i* patch.library/FreeStack ***************************************
- *
- * NAME
- * FreeStack -- Free memory for stack
- *
- * SYNOPSIS
- * FreeStack( patchstack)
- *
- * FreeStack( APTR );
- *
- * FUNCTION
- * Free memory for stack extension
- *
- *
- * INPUTS
- * patchstack = pointer to a PatchStack structure or NULL for no action.
- *
- * RESULT
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- void FreeStack( struct PatchStack *patchstack )
- {
- if( patchstack)
- {
- patchstack->PST_Magic1 = 0;
- patchstack->PST_Magic2 = NULL;
- patchstack = (struct PatchStack *)((UBYTE *)patchstack - patchstack->PST_Stacksize);
- FreeVec(patchstack);
- }
- }
- /****i* patch.library/AllocStackCached ***************************************
- *
- * NAME
- * AllocStackCached -- Allocate and initialize a new stack
- *
- * SYNOPSIS
- * patchstack = AllocStackCached( patch, stacksize )
- *
- * APTR AllocStackCached( struct Patch *, ULONG );
- * D0 A0 D0
- *
- *
- * FUNCTION
- * Allocate memory for stack extension
- *
- *
- * INPUTS
- * patch = patch structure to allocate stack for a stack.
- * stacksize = number of bytes, the new stack should hold.
- *
- * RESULT
- * patchstack = pointer to PatchStack structure or NULL on failure.
- *
- * NOTES
- * This function must be optimized for speed and stack-usage,
- * as it may be called from patch routines.
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- struct PatchStack * LIBFUNC AllocStackCached( REGA0 struct Patch *patch GNUC_REGA0, REGD0 ULONG stacksize GNUC_REGD0)
- {
- ULONG i, stacks;
- struct MasterPatch *master;
-
- stacks = MIN(STACKSLOTS,PatchBase->PB_StackExtensions);
- if( stacks)
- {
- master = GetMasterPatch( patch);
- for( i = 0; i < stacks; i++)
- {
- if(master->MPS_StackSlots[i])
- {
- if(master->MPS_StackSlots[i]->PST_Usage == NULL)
- {
- Disable();
- master->MPS_StackSlots[i]->PST_Usage = 1L; /* atomic */
- Enable();
- return(master->MPS_StackSlots[i]);
- }
- }
- }
- }
- if(PatchBase->PB_Flags & PBF_NoStackAllocmem)
- {
- return(NULL);
- }
-
- return( AllocStack(stacksize));
- }
- /****i* patch.library/FreeStackCached ***************************************
- *
- * NAME
- * FreeStackCached -- Free memory for stack
- *
- * SYNOPSIS
- * FreeStackCached( patchstack)
- *
- * FreeStackCached( APTR );
- * a1
- *
- * FUNCTION
- * Free memory for stack extension
- *
- *
- * INPUTS
- * patchstack = pointer to PatchStack structure or NULL for no action.
- *
- * RESULT
- *
- * NOTES
- * This function must be optimized for speed and stack-usage,
- * as it may be called from patch routines.
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- void LIBFUNC FreeStackCached( REGA1 struct PatchStack *patchstack GNUC_REGA1)
- {
- if(patchstack->PST_Usage)
- {
- Disable();
- patchstack->PST_Usage = 0L; /* atomic */
- Enable();
- }
- else
- {
- FreeStack( patchstack);
- }
- }
-
- /****i* patch.library/PatchMatch ***************************************
- *
- * NAME
- * PatchMatch -- Check, if a task is allowed to execute a patch
- *
- * SYNOPSIS
- * success = PatchMatch( tasklistheader)
- *
- * ULONG PatchMatch( struct TLHeader *);
- * D0 A0
- *
- * FUNCTION
- * Check, if a task is allowed to execute a patch
- *
- * INPUTS
- * tasklistheader = pointer to TLHeader structure.
- *
- * RESULT
- * success =
- *
- *
- * NOTES
- * This function must be optimized for speed and stack-usage,
- * as it may be called from patch routines.
- *
- * BUGS
- *
- * SEE ALSO
- *
- ******************************************************************************
- *
- */
-
- ULONG LIBFUNC PatchMatch( REGA0 struct TLHeader *list GNUC_REGA0)
- {
- struct Task *task;
- struct TLNode *pointer;
-
- task = SysBase->ThisTask;
-
- for (pointer = (struct TLNode *) list->TL_List.lh_Head;
- pointer->TN_Node.ln_Succ;
- pointer = (struct TLNode *)pointer->TN_Node.ln_Succ)
- {
-
- switch( pointer->TN_Node.ln_Type)
- {
- case TLI_TYPE_TASKID:
- if(task == (struct Task *)pointer->TN_Node.ln_Name)
- {
- return(list->TL_Result1);
- }
- break;
-
- case TLI_TYPE_TASKNAME:
- if( strcmp(task->tc_Node.ln_Name, pointer->TN_Node.ln_Name) == 0)
- {
- return(list->TL_Result1);
- }
- break;
-
- case TLI_TYPE_TASKPATTERN:
- if( MatchPatternNoCase( pointer->TN_Pattern, task->tc_Node.ln_Name))
- {
- return(list->TL_Result1);
- }
- break;
- }
- }
-
- return(list->TL_Result2);
- }
-
-
- /****i* patch.library/SAVEObtainSemaphoreShared ***************************************
- *
- * NAME
- * SAVEObtainSemaphoreShared -- Safely get shared access to the global semaphore
- *
- * SYNOPSIS
- * error = SAVEObtainSemaphoreShared( )
- *
- * ULONG error SAVEObtainSemaphoreShared( void);
- *
- * FUNCTION
- * Get shared access to the global patch.library semaphore without
- * breaking forbid() or disable() unless the global BreakForbid flag
- * has been set.
- *
- * INPUTS
- *
- * RESULT
- * error = errorcode as defined in patch.h
- *
- * NOTES
- * On V38 or less this function returns an exclusive semaphore.
- *
- * BUGS
- *
- * SEE ALSO
- * SAVEObtainSemaphore(), patch.h
- *
- ******************************************************************************
- *
- */
-
- ULONG SAVEObtainSemaphoreShared( void)
- {
- if(SysBase->LibNode.lib_Version < 39L)
- {
- return(SAVEObtainSemaphore());
- }
-
- if( (SysBase->IDNestCnt == -1 && SysBase->TDNestCnt == -1) ||
- (PatchBase->PB_Flags & PBF_BreakForbid))
- ObtainSemaphoreShared(&(PatchBase->PB_Semaphore));
- else
- {
- if( AttemptSemaphoreShared(&(PatchBase->PB_Semaphore)) == FALSE)
- return( PATERR_NoSemaphore);
- }
- return(PATERR_Ok);
- }
-
- /****i* patch.library/SAVEObtainSemaphore ***************************************
- *
- * NAME
- * SAVEObtainSemaphore -- Safely get access to the global semaphore
- *
- * SYNOPSIS
- * error = SAVEObtainSemaphore( )
- *
- * ULONG error SAVEObtainSemaphore( void);
- *
- * FUNCTION
- * Get access to the global patch.library semaphore without
- * breaking forbid() or disable() unless the global BreakForbid flag
- * has been set.
- *
- * INPUTS
- *
- * RESULT
- * error = errorcode as defined in patch.h
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- * SAVEObtainSemaphoreShared(), patch.h
- *
- ******************************************************************************
- *
- */
-
- ULONG SAVEObtainSemaphore( void)
- {
- if( (SysBase->IDNestCnt == -1 && SysBase->TDNestCnt == -1) || (PatchBase->PB_Flags & PBF_BreakForbid))
- ObtainSemaphore(&(PatchBase->PB_Semaphore));
- else
- {
- if( AttemptSemaphore(&(PatchBase->PB_Semaphore)) == FALSE)
- return( PATERR_NoSemaphore);
- }
- return(PATERR_Ok);
- }
-
- /****i* patch.library/TestPatchHandle ***************************************
- *
- * NAME
- * TestPatchHandle -- Test, if a pointer to a patch structure is valid.
- *
- * SYNOPSIS
- * error = TestPatchHandle( patch)
- *
- * ULONG error TestPatchHandle( struct Patch *);
- *
- * FUNCTION
- * Test, if a pointer to a patch structure is still valid.
- *
- * INPUTS
- * patch = pointer to a (hopefully) valid patch structure or NULL
- * for no action.
- *
- * RESULT
- * error = errorcode as defined in patch.h
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- * patch.h
- *
- ******************************************************************************
- *
- */
- ULONG TestPatchHandle( struct Patch *patch)
- {
- struct MasterPatch *master;
- struct Node *pointer;
- if( patch)
- {
- for( master = (struct MasterPatch *)(&(PatchBase->PB_MasterPatchHeader))->lh_Head;
- master->MPS_Node.ln_Succ;
- master = (struct MasterPatch *)master->MPS_Node.ln_Succ)
- {
- for( pointer = (struct Node *)(&(master->MPS_PatchHeader))->mlh_Head;
- pointer->ln_Succ;
- pointer = (struct Node *)pointer->ln_Succ)
- {
- if( pointer == (struct Node *)patch) return(PATERR_Ok);
- }
- }
- }
- return( PATERR_InvalidHandle);
- }
-
- /****i* patch.library/BAllocmem ***************************************
- *
- * NAME
- * BAllocmem -- Allocate memory from the memory pool remembering
- * its size.
- *
- * SYNOPSIS
- * memory = BAllocmem( size, attributes )
- *
- * APTR BAllocmem( ULONG, ULONG );
- *
- * FUNCTION
- * Allocate memory from the global or (if it exists) from a local
- * memory pool and remember its size.
- * Deallocate this memory with AFreemem().
- *
- * INPUTS
- * size = number of bytes to allocate
- * attributes = memory attributes (only required, if no local
- * memory pool is available)
- *
- * RESULT
- * memory = pointer to newly allocated memory block or NULL on failure
- *
- * NOTES
- *
- * BUGS
- *
- * SEE ALSO
- * Allocmem(), AllocVec(), AFreemem()
- *
- ******************************************************************************
- *
- */
-
-
- APTR BAllocmem( ULONG size, ULONG attr)
- {
- return( AAllocmem( size, attr, PatchBase->PB_MemoryPool));
- }
-
-